/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once

#include <string>

#include "IView2D.h"
#include "Image.h"
#include "../mmanager.h"
#include "../shared/geom.h"
#include "../game/Scene.h"
#include "../game/Tile.h"
#include "../game/QuestImporter.h"
#include "../Console.h"


/**
==========================================================
Map Change command
==========================================================
*/
class SceneManager;
class MapChange_f : public ICommand
{
public:
    MapChange_f() { sceneMng = NULL; };
    void Exec(std::string &s);
    ~MapChange_f() {};
    SceneManager* sceneMng;

};


/**
===========================
Loads a Scene (a map) and based off of the 
current camera, draws the map
===========================
*/
class ICamera;
class SceneManager
{
public:
    SceneManager(void);
	/** Load a scene */
    bool  LoadScene( const std::string &file );
    /** Unload the scene */
	void UnloadScene();

	/** Update the current scene */
    void Update(long dt);
	/** Draw the current Scene */
    void Draw(IRender* r, ICamera* cam);

    /** Get the current scene */
    Scene* GetCurrentScene() { return m_currentScene; };

private:
	// the current scene to display
    Scene* m_currentScene;

    // import our quest
    QuestImporter m_importer;

    // Map change cmd
    MapChange_f     map_f;

public:
    virtual ~SceneManager(void);
};









/*------------------------------------
Will use later for QuadTree implementation
-------------------------------------*/


//
//
//
//#define MAX_CHILDREN 4
//
///**
//==========================
//Generic Node - has 4 children
//QuadTree implementation
//==========================
//*/
//class Node : public IMMObject
//{
//public:
//    Node() {};
//    
//    Node( int x, int y, int w, int h ) {
//        m_bounds.x =x;
//        m_bounds.y =y;
//        m_bounds.width =w;
//        m_bounds.height = h;
//    };
//
//    Node( CMMPointer<Node> &Parent, int x, int y, int w, int h ) :
//    m_parent( Parent ) {
//        m_bounds.x =x;
//        m_bounds.y =y;
//        m_bounds.width =w;
//        m_bounds.height = h;
//    };
//
//    Node( CMMPointer<Node> &Parent, Rect &r) :
//    m_parent( Parent ), m_bounds( r ) {};
//
//    CMMPointer<IView2D>  &GetIView2D() { return m_view; };
//    void SetIView2D( const CMMPointer<IView2D> &v ) { m_view = v; };
//
//    /**
//     *  Render this nodes children
//     */
//    virtual void Render( IRender *r ) {
//        // r->DrawRect( m_bounds.x, m_bounds.y, m_bounds.width, m_bounds.height );
//        for ( int i = 0; i < MAX_CHILDREN; i++ )
//        {
//            m_leafs[i]->Render( r );
//        }
//    };
//
//    CMMPointer<Node> &GetParent() { return m_parent; };
//	
//    virtual CMMPointer<Node> GetLeft() { return m_leafs[0]; };
//    virtual CMMPointer<Node> GetRight() { return m_leafs[1]; };
//	
//	virtual CMMPointer<Node> GetTop() { return m_leafs[2]; };
//	virtual CMMPointer<Node> GetBottum() { return m_leafs[3]; };
//
//    void SetLeft( CMMPointer<Node> &n ) {
//        m_leafs[0] = n;
//    };
//
//    void SetRight( CMMPointer<Node> &n ) {
//        m_leafs[1] = n;
//    };
//    
//    void SetTop( CMMPointer<Node> &n ) {
//        m_leafs[2] = n;
//    };
//
//    void SetBottum( CMMPointer<Node> &n ) {
//        m_leafs[3] = n;
//    };
//
//    void SetBounds( Rect &r ) { m_bounds = r; }; 
//
//    Rect GetBounds() { return m_bounds; };
//
//    AUTO_SIZE;
//
//    virtual ~Node() {};
//protected:
//    CMMPointer<IView2D> m_view;
//    CMMPointer<Node>    m_leafs[MAX_CHILDREN];
//    CMMPointer<Node>    m_parent;
//
//    Rect                m_bounds;
//
//};
//
///**
//==============================
//The leaf node actually holds the
//Tile to be drawn
//==============================
//*/
//class LeafNode : public Node
//{
//public:
//    LeafNode() : Node() {};
//
//    LeafNode(CMMPointer<Node> &Parent, int x, int y, int w, int h,CMMPointer<IView2D> &v  ) :
//    Node(Parent, x, y, w, h ){ m_view = v; };
//
//    LeafNode(CMMPointer<Node> &Parent, Rect &r, CMMPointer<IView2D> &v ) :
//    Node( Parent, r) { m_view = v; };
//    /**
//     * Render this tile (node)
//     */
//    void Render( IRender *r ) {
//        this->GetIView2D()->Render( r );
//    };
//
//    CMMPointer<Node> GetLeft() { return NULL; };
//    CMMPointer<Node> GetRight() { return NULL; };
//	CMMPointer<Node> GetTop() { return NULL; };
//	CMMPointer<Node> GetBottum() { return NULL; };
//
//    AUTO_SIZE;
//    virtual ~LeafNode() {};
//};
//
///**
//==============================
//Map Layer
//==============================
//*/
////class Layer : public IMMObject
////{
////public:
////    
////};

//int SceneManager::CreateScene(CMMPointer<Node> root)
//{
//    //int nw = (root->GetBounds().width / 2) ;
//    //int nh = (root->GetBounds().height / 2);
//
//    ////std::cout << "nw = " << nw << std::endl;
//    //if ( nw < (m_tileWidth*2) && nh < (m_tileHeight*2) )
//    //{
//    //    int x1 = root->GetBounds().x;
//    //    int y1 = root->GetBounds().y;
//    //    CMMPointer<Tile> tile1 = new Tile();
//    //    //tile1->Init( g_kernel->GetResource()->LoadImage( "tile.tga" ), x1,y1 );
//    //    tile1->Init( g_kernel->GetResource()->LoadImage( "tile_a.bmp" ), x1,y1 );
//    //    root->SetLeft ( CMMPointer<Node>(new LeafNode(  root, x1, y1, m_tileWidth, m_tileHeight, CMMPointer<IView2D>(tile1) )) );
//    //    
//    //    int x2 = root->GetBounds().x + m_tileWidth;
//    //    int y2 = root->GetBounds().y;
//    //    CMMPointer<Tile> tile2 = new Tile();
//    //    //tile2->Init( g_kernel->GetResource()->LoadImage( "tile.tga" ), x2,y2 );
//    //    tile2->Init( g_kernel->GetResource()->LoadImage( "tile_a.bmp" ), x2,y2 );
//    //    root->SetRight( CMMPointer<Node>(new LeafNode(  root, x2, y2, m_tileWidth, m_tileHeight, CMMPointer<IView2D>(tile2) )) );
//    //   
//    //    int x3 = root->GetBounds().x;
//    //    int y3 = root->GetBounds().y + m_tileHeight;
//    //    CMMPointer<Tile> tile3 = new Tile();
//    //    //tile3->Init( g_kernel->GetResource()->LoadImage( "tile.tga" ), x3,y3 );
//    //    tile3->Init( g_kernel->GetResource()->LoadImage( "tile_a.bmp" ), x3,y3 );
//    //    root->SetTop  ( CMMPointer<Node>(new LeafNode(  root, x3, y3, m_tileWidth, m_tileHeight, CMMPointer<IView2D>(tile3) )) );
//    //    
//    //    int x4 = root->GetBounds().x + m_tileWidth;
//    //    int y4 = root->GetBounds().y + m_tileHeight;
//    //    CMMPointer<Tile> tile4 = new Tile();
//    //    //tile4->Init( g_kernel->GetResource()->LoadImage( "tile.tga" ), x4,y4 );
//    //    tile4->Init( g_kernel->GetResource()->LoadImage( "tile_a.bmp" ), x4,y4 );
//    //    root->SetBottum( CMMPointer<Node>(new LeafNode( root, x4, y4, m_tileWidth, m_tileHeight, CMMPointer<IView2D>(tile4) )) );
//
//    //    m_tileCount += 4;
//    //} else {
//    //    // Create children
//    //    CMMPointer<Node> left   = new Node(  root, root->GetBounds().x,    root->GetBounds().y,    nw, nh );
//    //    CMMPointer<Node> right  = new Node(  root, root->GetBounds().x+nw, root->GetBounds().y,    nw, nh );
//    //    CMMPointer<Node> top    = new Node(  root, root->GetBounds().x,    root->GetBounds().y+nh, nw, nh );
//    //    CMMPointer<Node> bottum = new Node(  root, root->GetBounds().x+nw, root->GetBounds().y+nh, nw, nh );
//    //
//    //    // set the children
//    //    root->SetLeft( left );
//    //    root->SetRight( right );
//    //    root->SetTop( top );
//    //    root->SetBottum( bottum );
//
//    //    // build children
//    //    CreateScene( left );
//    //    CreateScene( right );
//    //    CreateScene( top );
//    //    CreateScene( bottum );
//
//    //}
//    return 0;
//}
//
//
//bool SceneManager::IsInBounds( CMMPointer<Node> root, IRender *r)
//{
//    
//    if ( root == NULL )
//        return false;
//   
//    // Test if the landscape is in the view of the camera
//    CMMPointer<ICamera> cam = r->GetCamera();
//
//    // first check leafnodes
//    if ( root->GetLeft() == NULL ) {//&& cam->Contains ( root->GetBounds() ) ) {
//        root->Render( r );
//        m_visibleTiles++;
//        return false;
//    }
//    if ( root->GetRight() == NULL ) {//&& cam->Contains ( root->GetBounds() ) ) {
//        root->Render( r );
//        m_visibleTiles++;
//        return false;
//    }
//    if ( root->GetTop() == NULL ){//&& cam->Contains ( root->GetBounds() )) {
//        root->Render( r );
//        m_visibleTiles++;
//        return false;
//    }
//    if ( root->GetBottum() == NULL ){//&& cam->Contains ( root->GetBounds() )) {
//        root->Render( r );
//        m_visibleTiles++;
//        return false;
//    }
//
//    // Test to see where the camera is, and only
//    // draw the needed tiles
//    if( cam->Contains ( root->GetLeft()->GetBounds() ) )
//        IsInBounds ( root->GetLeft(),  r );
//    if( cam->Contains ( root->GetRight()->GetBounds() ) )
//        IsInBounds (root->GetRight(), r );
//    if( cam->Contains ( root->GetTop()->GetBounds() ) )
//        IsInBounds (root->GetTop(), r );
//    if( cam->Contains ( root->GetBottum()->GetBounds() ) )
//        IsInBounds (root->GetBottum(), r );
//
//    return true;
//}